import json
import threadpool
from ..config.enum_config import RequestMethod, ContentType
from ..lib.result_code import DEFAULT_CODE, PARAMS_IS_INVALID, \
    PARAMS_IS_NULL, CustomErrNo
from ..lib.utils import check_param_is_complete, not_null_check_with_errmsg, \
    format_request_body_to_dict


class BaseService:
    """
    业务处理父类
    """

    def __init__(self, request=None):
        if request is None:
            raise ValueError("request is not None")
        self.request = request
        self.param_check_msg = ""
        self.param_check_errno = 0
        self.param_serial_dict = dict()
        self.pagination = True
        self.serial_param()

    def serial_param(self):
        """
        序列化参数，统一将参数转化为dict
        :return:
        """
        try:
            method = self.request.method
            res = dict()
            if method == RequestMethod.REQ_GET:
                res = self.request.GET.dict()
            if method == RequestMethod.REQ_POST:
                success, res = format_request_body_to_dict(self.request.body)
                if not success:
                    self.param_check_msg = PARAMS_IS_INVALID
                    self.param_check_msg = res
                    return False
            if method == RequestMethod.REQ_PUT:
                success, res = format_request_body_to_dict(self.request.body)
                if not success:
                    self.param_check_msg = PARAMS_IS_INVALID
                    self.param_check_msg = res
                    return False
            if method == RequestMethod.REQ_DELETE:
                success, res = format_request_body_to_dict(self.request.body,
                                                           content_type=ContentType.FORM_URLENCODED)
                if not success:
                    self.param_check_msg = PARAMS_IS_INVALID
                    self.param_check_msg = res
                    return False
            self.param_serial_dict = res
            pagination = self.param_serial_dict.get("pagination")
            if pagination == "false":
                self.pagination = False
        except Exception as e:
            print("BaseService serial param failed,errmsg {}".format(str(e)))

    def add_param_serial(self, **kwargs):
        """
        更新参数，带到下游统一处理
        :param kwargs:
        :return:
        """
        self.param_serial_dict.update(kwargs)

    def param_serial_dict(self):
        """
        清空参数
        :return:
        """
        self.param_serial_dict = dict()

    def restful_param_check(self, complete_check: list = None,
                            null_check: list = None):
        """
        restful 参数校验
        :param complete_check:
        :param null_check:
        :return:
        """
        # 参数完整性检验，判断参数是否存在
        if complete_check:
            success, res = check_param_is_complete(self.param_serial_dict, complete_check)
            if not success:
                self.param_check_msg = PARAMS_IS_INVALID
                self.param_check_msg = res
                return False
        # 参数空检验，判断参数是否为空
        if null_check:
            success, res = check_param_is_complete(self.param_serial_dict, null_check)
            if not success:
                self.param_check_msg = PARAMS_IS_INVALID
                self.param_check_msg = "param null check failed, reason {}".format(msg)
                return False

        return True

    def param_check_response_format_json(self):
        """
        将restful分格参数校验结果返回
        :return:
        """
        if self.param_check_msg:
            return CustomErrNo(status_code=self.param_check_errno,
                               msg=self.param_check_msg).to_json()
        else:
            return CustomErrNo(status_code=self.param_check_errno).to_json()

    def query_filter(self, source_param: dict = None,
                     filter_key_list: list = None,
                     filter_contains: list = None):
        """
        检索条件过滤，filter_key_list中的参数将从参数字典删除，filter_contains列表中是模糊查询参数
        :param source_param:
        :param filter_key_list:
        :param filter_contains:
        :return:
        """
        if not filter_key_list:
            filter_key_list = list()
        filter_key_list += ["page_size", "page_index", "pagination"]

        if source_param is None:
            source_param = self.param_serial_dict.copy()

        for param_key in list(source_param.keys()):
            if source_param.get(param_key) == "" or param_key in filter_key_list:
                del source_param[param_key]

        if filter_contains:
            for contains in filter_contains:
                if not source_param.get(contains):
                    continue
                source_param["{}__icontains".format(contains)] = source_param.get(contains)
                del source_param[contains]

        return source_param


    @staticmethod
    def thread_pool_send(function, args_list: list, num_workers=5):
        """
        多线程处理请求
        :param function:
        :param args_list:
        :param num_workers:
        :return:
        """
        pool = threadpool.ThreadPool(num_workers)
        requests = threadpool.makeRequests(function, args_list)
        [pool.putRequest(req) for req in requests]
        pool.wait()

